/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */
#ifndef __PQ_TerrainObject_H__
#define __PQ_TerrainObject_H__

#include "GameObject.h"
#include "TerrainComponent.h"

#include "OgreTerrain.h"//terrain

namespace PQEngine
{
	//linked list ,mainly for physics use
	//TerrainObject is inherit GameObject for we can attach component to it
	class TerrainObject
		: public GameObject
	{
	public:
		typedef std::map<Ogre::Terrain*,TerrainObject*> TerrainList;//for seach using terrain pointer
		typedef std::map<int,TerrainObject*> TerrainObjectList;//for search using slot
	protected:
		TerrainObject(SceneObject* sceneObject,Ogre::Terrain* terrain,int slotX,int slotY);
	public:
		static TerrainObject* addTerrain(SceneObject* sceneObject, Ogre::Terrain* terrain,int slotX,int slotY);
		static TerrainObject* get(int slotX,int slotY);
		static TerrainObject* get(Ogre::Terrain* terrain);
		static Ogre::Vector3 getSlotPosition(int slotX,int slotY);
		
		/*Add terrain texture layer with specified name.
		*/
		void addLayer(std::string textureName);

		/*Add terrain texture layer with specified texture index.
		*/
		void addLayer(int textureIndex);

		/*Select current terrain object.
		*/
		void selectObject(bool selected);

		inline bool hasSelectedLayer()
		{
			return (_selectedLayer!=-1);
		}

		inline void selectLayer(int index)
		{
			int size=_layerTextureList.size();
			if(index>=0&&index<size){
				_selectedLayer=index;
			}else{
				_selectedLayer=-1;
			}
		}

		inline int getSelectedLayer()
		{
			return _selectedLayer;
		}

		inline StringVector getLayerNameList()
		{
			return _layerTextureList;
		}

		inline int getLayerCount()
		{
			return _layerTextureList.size();
		}


		float* getHeightData();

		inline Ogre::Terrain* getTerrain()
		{
			return _terrain;
		}

		TerrainComponent* getTerrainComponent();

		//bottom left point's world coord
		inline Ogre::Vector3 getWorldPosition()
		{
			Ogre::Vector3 position;
			Ogre::Vector3 center=_terrain->getPosition();
			_terrain->getPoint(0,0,&position);
			
			return position+center;
		}

		inline void setRestitution(float restitution)
		{
			_restitution=restitution;
		}

		inline float getRestitution()
		{
			return _restitution;
		}

		inline void setFriction(float friction)
		{
			_friction=friction;
		}

		inline float getFriction()
		{
			return _friction;
		}

		inline float getWorldSize()
		{
			return _terrain->getWorldSize();
		}

		inline Ogre::AxisAlignedBox getWorldAABB()
		{
			return _terrain->getWorldAABB();
		}

		inline float getMinHeight()
		{
			return _terrain->getMinHeight();
		}

		inline float getMaxHeight()
		{
			return _terrain->getMaxHeight();
		}

		inline static TerrainObject* head()
		{
			return _head;
		}

		inline TerrainObject* next()
		{
			return _next;
		}

		inline void setNext(TerrainObject* next)
		{
			_next=next;
		}

		inline TerrainObject* current()
		{
			return _current;
		}

	private:
		static TerrainObjectList _list;
		static TerrainList _terrainList;
		static TerrainObject* _head;
		static TerrainObject* _current;

		TerrainObject* _next;

		Ogre::Terrain* _terrain;
		int _slotX;
		int _slotY;

		Ogre::Vector3 _worldPosition;
		
		TerrainComponent* _terrainComponent;//quick ref
		float *_heightData;

		float _restitution;
		float _friction;
		
		StringVector _layerTextureList;//layer texture name list
		int _selectedLayer;
	};
}
#endif
